#pragma once

template <typename Key, typename Val>
struct _hHashMapNodeBase
{
	using _HashVec = hHashVector<uint16_t, _hHashMapNodeBase<Key, Val>*>;
	using _HashVecIt = typename _HashVec::Iter;

	std::pair<uint8_t, _HashVecIt> _idx;
	_hHashMapNodeBase* _parent = NULL;

	std::pair<const Key, Val>* _pValPr = NULL;
	_HashVec* _pHashVec = NULL;

	_hHashMapNodeBase(uint8_t idx);
	virtual ~_hHashMapNodeBase() {}

	_hHashMapNodeBase* getNext();
};

template <typename Key, typename Val, typename Hash, size_t FstP, size_t... RestP>
struct _hHashMapNode<Key, Val, Hash, FstP, RestP...> : public _hHashMapNodeBase<Key, Val>
{
	using _Base = _hHashMapNodeBase<Key, Val>;
	using _NextNode = _hHashMapNode<Key, Val, Hash, RestP...>;

	_hHashMapNode(uint8_t idx = 0) : _hHashMapNodeBase<Key, Val>(idx) {}

	template<typename... Args>
	std::pair<_hHashMapIterator<Key, Val, Hash>, bool> emplaceCallBack(_hHashMapIterator<Key, Val, Hash>& it, size_t hash, const Key& k, Args... args);
	_hHashMapIterator<Key, Val, Hash> findCallBack(_hHashMapIterator<Key, Val, Hash>& it, size_t hash, const Key& k);

	std::ostream& fillDebug(std::ostream& os, uint8_t idx = 0) const;
};

template<typename Key, typename Val, typename Hash, size_t P>
struct _hHashMapNode<Key, Val, Hash, P> : public _hHashMapNodeBase<Key, Val>
{
	using _Base = _hHashMapNodeBase<Key, Val>;
	_hHashMapNode(uint8_t idx = 0) : _hHashMapNodeBase<Key, Val>(idx) {}

	template<typename... Args>
	std::pair<typename hHashMap<Key, Val, Hash>::Iter, bool> emplaceCallBack(_hHashMapIterator<Key, Val, Hash>& it, size_t, const Key& k, Args... args);
	_hHashMapIterator<Key, Val, Hash> findCallBack(_hHashMapIterator<Key, Val, Hash>& it, size_t, const Key& k);
	std::ostream& fillDebug(std::ostream& os, uint8_t idx = 0) const;
};
